home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / setdir2.arc / SETDIR1.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-12-05  |  25.2 KB  |  681 lines

  1.                  PAGE   60,132 
  2.  
  3.                  ;Usage is: call envsub  ds:si -> length,string
  4.  
  5.                  ;      string is of form: name=value
  6.  
  7.                  ;clone of SET command that demonstrates updating
  8.                  ;      the environment string.
  9.                  ;If there is no secondary command processor, the
  10.                  ;      global environment is updated
  11.                  ;If there is a secondary command processor, then
  12.                  ;      its enviroment is updated
  13.  
  14. sb               segment at 0      ;equates storage blocks and psp's
  15.  
  16. sb_kind          db     ' '        ;type of storage block: 'M' or 'Z'
  17. sb_psp           dw     ?          ;psp segment address
  18. sb_length        dw     ?          ;sb length in paragraphs
  19. sb_head_length   equ    10h        ;length of sb header
  20.  
  21.                  org    0h         ;program segement prefix equates
  22. psp_ret_int      dw     ?          ;int 20h
  23.                  org    2Ch
  24. psp_env          dw     ?          ;segment address of environment
  25.                  org    50h
  26. psp_dos_function dw     ?          ;address of function dispatcher
  27.                  org    80h
  28. psp_parm_string  db     ?          ;1 byte length plus parm string
  29.  
  30. psp_length       equ    100h
  31.  
  32. sb               ends
  33.  
  34. code_seg         segment para public
  35.                  assume cs:code_seg,ds:code_seg,es:sb
  36.                  public env_set
  37.                        
  38.                  ;local  data
  39.  
  40. cr               equ    13
  41. lf               equ    10
  42.  
  43. sb_count         dw    0            ;count of sb's encountered
  44. sb_shell         dw    0            ;segment address of shell  sb
  45. sb_shell_env     dw    0            ;segment address of global env sb
  46. sb_secondary     dw    0            ;segment address of secondary command.com
  47. sb_secondary_env dw    0            ;segment address of secondary command env
  48.  
  49. fatal_msg       equ    80h 
  50. error_msg       equ    40h 
  51. info_msg        equ    20h
  52. msg_flag        db     fatal_msg+error_msg
  53.  
  54. secondary_msg   db     info_msg,'Secondary '
  55. command_found   db     info_msg,'COMMAND.COM found',cr,lf,'$'
  56. bad_dos_msg     db     fatal_msg,'Must be running under DOS 2.0 or above',cr,lf,'$'
  57. bad_sb_msg      db     fatal_msg,'Bad storage block',cr,lf,'$'
  58. bad_env_msg     db     error_msg,'Bad environment block',cr,lf,'$'
  59. command_lost    db     error_msg,'Shell never found',cr,lf,'$'
  60. addbadmsg       db     error_msg,'Environment corrupt',cr,lf,'$'
  61. addmsg          db     info_msg,'Addition requested',cr,lf,'$'
  62. removemsg       db     info_msg,'Removal requested',cr,lf,'$'
  63. env_set_nospace db     error_msg,'No space in environment string',cr,lf,'$'
  64. env_set_syntax  db     error_msg,'Set string syntax error',cr,lf,'$'
  65.  
  66. type_string     proc   near          ;type message at offset in dx
  67.                 push   ax            ;save registers
  68.                 push   cx
  69.                 push   dx
  70.                 push   si
  71.  
  72.                 mov    si,dx         ;get message level
  73.                 lodsb 
  74.                 and    al,msg_flag   ;compare to what sells
  75.                 jz     type_ret      ;if not on list, send to bit bucket
  76.  
  77.                 mov    dx,si
  78.                 mov    ax,0900h
  79.                 int    21h
  80. type_ret:
  81.                 pop    si
  82.                 pop    dx
  83.                 pop    cx
  84.                 pop    ax
  85.                 ret
  86. type_string     endp
  87.  
  88. get_first_sb    proc   near       ;get first storage block, point es at it
  89.                 push   ax
  90.                 push   bx
  91.                 mov    ax,5200h       
  92.                 int    21h        ;es:bx points to memory block anchor+2
  93.                 dec    bx
  94.                 dec    bx
  95.                 mov    es,es:[bx] ;get first memory block address into es
  96.                 pop    bx
  97.                 pop    ax
  98.                 ret
  99. get_first_sb    endp
  100.  
  101. get_next_sb     proc   near
  102.                 push   ax
  103.                 mov    ax,es             ;get current paragraph
  104.                 add    ax,sb_length      ;add in number of paragraphs
  105.                 inc    ax                ;add 1 for header
  106.                 mov    es,ax             ;set new extra segment address
  107.                 pop    ax
  108.                 ret
  109. get_next_sb     endp
  110.  
  111.  
  112. find_secondary_env proc  near       ;find env sb's for current program sb
  113.                 push   ax           ;pointed to by es
  114.                 push   es
  115.                 mov    ax,es        ;get address of secondary cp's sb
  116.                 inc    ax           ;get its psp address
  117. find_secondary_env_loop:
  118.                 call   get_next_sb  ;get next sb
  119.                 cmp    ax,sb_psp    ;match secondary's psp?
  120.                 jne    find_secondary_env_next    ;if not, skip
  121.  
  122.                 mov    sb_secondary_env,es        ;otherwise, save
  123. find_secondary_env_next:
  124.                 cmp    sb_kind,'Z'                ;last block?
  125.                 jne    find_secondary_env_loop
  126.  
  127.                 pop    es
  128.                 pop    ax
  129.                 ret
  130. find_secondary_env endp
  131.  
  132. command_test    proc   near         ;test program storage block at es:0
  133.                 push   ax
  134.                 push   bx
  135.                 push   cx
  136.                 push   dx
  137.                 push   ds
  138.                 push   es
  139.                 push   si
  140.  
  141.                 cmp    sb_count,2
  142.                 ja     command_second
  143.  
  144.                 mov    dx,offset command_found
  145.                 call   type_string
  146.                 mov    sb_shell,es
  147.                 jmp    command_test_good
  148.  
  149. command_second: 
  150.                 cmp    sb_shell,0                       ;did we find shell?
  151.                 je     command_first_bad                ;if not, error
  152.  
  153.                 cmp    word ptr es:psp_env+sb_head_length,0  ;check environment of program
  154.                 je     command_test_good                 ;if no environment, quit
  155.  
  156.                 push   sb_shell
  157.                 pop    ds                               ;ds points to shell
  158.                 mov    al,byte ptr es:sb_head_length+psp_length 
  159.                 cmp    al,0E9h                          ;a JMP?
  160.                 jne    command_test_good                ;if not, no harm done
  161.  
  162.                 cmp    al,byte ptr ds:sb_head_length+psp_length   ;check 1st instruction 
  163.                 jne    command_first_bad
  164.  
  165.                 mov    si,sb_head_length+psp_length               
  166.                 mov    di,sb_head_length+psp_length               
  167.                 mov    cx,10      ;look at 10 words of code
  168.                 repz   cmpsw
  169.                 clc
  170.                 jcxz   command_test_found   ;if they all match, fine
  171.  
  172.                 jmp    command_test_good    ;if not, no harm done
  173.  
  174. command_test_found:
  175.                 push   cs
  176.                 pop    ds
  177.                 mov    sb_secondary,es
  178.  
  179.                 mov    ax,es:psp_env+sb_head_length     ;get env address
  180.                 dec    ax                               ;back up over sb header
  181.                 mov    sb_secondary_env,ax              ;and save it
  182.  
  183.                 call   find_secondary_env               ;look for other env's
  184.  
  185.                 mov    dx,offset secondary_msg
  186.                 call   type_string
  187.                 jmp    command_test_good
  188.  
  189. command_first_bad:
  190.                 mov    dx,offset command_lost
  191.                 call   type_string
  192.                 stc
  193.                 jmp    command_test_end
  194.  
  195. command_test_good:
  196.                 clc
  197. command_test_end:
  198.                 pop    si
  199.                 pop    es
  200.                 pop    ds
  201.                 pop    dx
  202.                 pop    cx
  203.                 pop    bx
  204.                 pop    ax
  205.  
  206.                 ret
  207. command_test    endp
  208.  
  209.  
  210.  
  211. prog_test       proc   near         ;test block for program
  212.                 push   ax           ;save registers
  213.                 push   cx
  214.                 push   dx
  215.                 push   es
  216.  
  217.                 mov    ax,sb_psp             ;get PSP of owner
  218.                 cmp    ax,0                  ;if zero, it is free
  219.                 je     prog_exit
  220.  
  221.                 cmp    ax,8                  ;if PSP of owner is at 8
  222.                 je     prog_exit             ;block owned by config.sys
  223.                 
  224.                 sub    ax,sb_head_length     ;get address of sb containg program
  225.                 cmp    ax,sb_shell           ;is owner the primary shell?
  226.                 je     prog_exit
  227.                 push   es
  228.                 pop    ax
  229.                 cmp    ax,sb_psp             ;compare to address of owner
  230.                 ja     prog_exit             ;if owner below SB, system-owned
  231.  
  232.                 add    ax,sb_length          ;add in length
  233.                 cmp    ax,sb_psp             ;compare to owner's PSP
  234.                 JB     prog_exit             ;if end below owner PSP, no program
  235.                 cmp    sb_length,10          ;is block long enough to have a psp?
  236.                 jbe    prog_exit             ;if not, no program
  237.  
  238.                 mov    ax,word ptr es:psp_dos_function+sb_head_length 
  239.                 cmp    ax,word ptr cs:psp_dos_function   ;check PSP validity  
  240.                 jne    prog_exit           
  241.  
  242.                 mov    ax,word ptr es:psp_ret_int+sb_head_length
  243.                 cmp    ax,word ptr cs:psp_ret_int     ;check PSP validity
  244.                 jne    prog_exit                ;if invalid, skip looking for env
  245.  
  246.                 call   command_test
  247.                 clc
  248. prog_exit:
  249.  
  250.                 pop    es                       ;restore registers
  251.                 pop    dx
  252.                 pop    cx
  253.                 pop    ax
  254.                 ret
  255.  
  256. prog_test       endp
  257.  
  258. sb_scan         proc   near           ;loop cx storage blocks
  259.  
  260.                 mov    al,sb_kind     ;get storage block type byte
  261.                 cmp    al,04dh        ;ordinary storage block
  262.                 je     sb_scan_got 
  263.                 cmp    al,05ah
  264.                 jne    sb_scan_bad
  265.                 mov    cx,1           ;last block
  266.  
  267. sb_scan_got:        
  268.                 inc    sb_count              ;count storage blocks
  269.  
  270.                 cmp    sb_count,3
  271.                 jne    sb_scan_not_global
  272.                       
  273.                 mov    sb_shell_env,es
  274.                 jmp    sb_scan_get
  275.  
  276. sb_scan_not_global:
  277.                 call   prog_test             ;look for program
  278.  
  279.                 loop   sb_scan_get 
  280.                 jmp    sb_scan_end
  281.  
  282. sb_scan_get:
  283.                 call   get_next_sb
  284.                 jmp    sb_scan
  285.  
  286. sb_scan_end:
  287.                 clc
  288.                 jmp    sb_scan_exit
  289.  
  290. sb_scan_bad:
  291.                 mov    al,2
  292.                 mov    dx,offset bad_sb_msg
  293.                 stc
  294.  
  295. sb_scan_exit:          
  296.                 ret
  297. sb_scan         endp
  298.  
  299.  
  300. sb_anal         proc   near            ;proc to analyze storage blocks
  301.  
  302.                 push   cx
  303.                 push   dx             ;carry flag = error
  304.                 push   es             ;error level in al
  305.                 mov    ah,30h         ;get release number
  306.                 int    21h
  307.                 cmp    al,01h         ;above dos 1.x?
  308.                 jna    sb_bad_dos
  309.  
  310.                 cld                  ;clear direction flag
  311.                 call   get_first_sb
  312.                 mov    cx,9999        ;scan all blocks
  313.                 call   sb_scan 
  314.                 jc     sb_send_msg    ;if any errors, exit
  315.  
  316.                 jmp    sb_exit
  317.  
  318. sb_bad_dos:
  319.                 mov    al,1
  320.                 mov    dx,offset bad_dos_msg
  321.                 stc
  322.                 jmp    sb_send_msg
  323.  
  324. sb_bad_env:
  325.                 mov    al,3
  326.                 mov    dx,offset bad_env_msg
  327.                 stc
  328. sb_send_msg:             
  329.                 pushf
  330.                 call   type_string
  331.                 popf    
  332. sb_exit:
  333.                 pop    es
  334.                 pop    dx
  335.                 pop    cx
  336.  
  337.                 ret
  338. sb_anal         endp
  339.  
  340. make_upper     proc    near          ;make cx bytes at es:di upper case
  341.  
  342.                push    ax            ;save registers modified
  343.                push    cx
  344.                push    di
  345.                push    ds
  346.                push    si
  347.  
  348.                push    es
  349.                pop     ds
  350.                mov     si,di
  351. make_upper_loop:
  352.                lodsb                  ;get a byte
  353.                cmp     al,'a'           ;if lower case:
  354.                jb      make_upper_next
  355.                cmp     al,'z'
  356.                ja      make_upper_next
  357.                and     al,255-'a'+'A'   ;make upper case
  358. make_upper_next:
  359.                stosb                  ;store out results
  360.                loop    make_upper_loop
  361.  
  362.                pop     si            ;restore registers
  363.                pop     ds
  364.                pop     di
  365.                pop     cx
  366.                pop     ax
  367.                ret
  368. make_upper     endp
  369.  
  370.  
  371.  
  372. env_var_name  proc     near               ;find environment variable name at
  373.               push     ax                 ;  ds:si, length in cx
  374.               push     bx                 ;at exit, ds:di points to name
  375.               push     di                 ;         name length in cx
  376.               push     es                 ;variable contents length to dx
  377.  
  378.               push     cx                 ;save length and pointer
  379.               push     si                 ;for error exits
  380.  
  381.               jcxz     env_var_name_bad   ;if length is 0, exit
  382.  
  383.  
  384.               push     cs                 ;scan works at es:di
  385.               pop      es
  386.               mov      di,si
  387.               mov      al,' '             ;scan for non-blank
  388.  
  389. env_var_strip:
  390.               repz     scasb              ;look for non-blank
  391.               jcxz     env_var_name_bad   ;if all blank, error!
  392.  
  393.               inc      cx                 ;back up over non-blank character
  394.               dec      di
  395.               mov      si,di              ;save start of non-blank string  
  396.               mov      bx,cx              ;save length
  397.  
  398.               repnz    scasb              ;look for a blank
  399.               mov      dx,di              ;save location of ' ' or end 
  400.  
  401.               mov      cx,bx              ;reset search length
  402.               mov      di,si              ;reset search pointer
  403.               mov      al,'='             ;search for equals sign
  404.               repnz    scasb
  405.               jne      env_var_name_bad   ;if not found, error
  406.  
  407.               cmp      di,dx              ;compare location of '=' and ' '
  408.               ja       env_var_name_bad   ;found ' ' first? then exit
  409.  
  410.               mov      dx,bx              ;restore search length
  411.               add      dx,si              ;add start
  412.               sub      dx,di              ;subtract where '=' was
  413.  
  414.               pop      ax                 ;pop old si from stack
  415.               pop      ax                 ;pop old cx from stack
  416.  
  417.               mov      cx,di              ;where we found '='
  418.               sub      cx,si              ;subtract string start
  419.               dec      cx                 ;minus 1 for '='
  420.               clc                         ;all is well
  421.               jmp      env_var_name_exit
  422.  
  423. env_var_name_bad:
  424.               pop      si                 ;restore pointer and length
  425.               pop      cx
  426.               xor      dx,dx              ;contents length assumed zero
  427.               stc                         ;problems  - set carry
  428.  
  429. env_var_name_exit:                       
  430.               pop      es
  431.               pop      di
  432.               pop      bx                 ;restore registers
  433.               pop      ax
  434.               ret
  435.  
  436. env_var_name  endp
  437.  
  438. get_sb_size   proc     near              ;get byte size of sb at es:0 in cx
  439.               push     ax
  440.               mov      ax,sb_length      ;get length of env in paragraphs
  441.               mov      cl,4              ;times 16
  442.               shl      ax,cl
  443.               mov      cx,ax
  444.               pop      ax
  445.               ret
  446. get_sb_size   endp
  447.  
  448. env_var_find  proc     near              ;find environment variable
  449.                                          ;named in ds:si,name length in cx 
  450.                                          ;return string start in es:di
  451.                                          ;length of entire string in cx 
  452.               push     ax                ;save registers
  453.               push     bx
  454.               push     dx
  455.  
  456.               mov      bx,cx             ;save length of name
  457.               push     es                ;save env block address      
  458.               push     ds                ;set  es:di to source string
  459.               pop      es                ;     "
  460.               mov      di,si             ;make name upper case
  461.               call     make_upper        ;altering input string
  462.               pop      es                ;restore es to environment block
  463.  
  464.               call     get_sb_size       ;get size of sb in bytes
  465.  
  466.               mov      di,sb_head_length ;start at data portion of block
  467.               mov      dx,cx             ;save block length
  468.  
  469. env_var_find_loop:
  470.               push     si                ;save string pointers
  471.               push     di
  472.  
  473.               mov      cx,bx             ;compare for length of name
  474.               mov      ah,1              ;say not compare
  475.               repz     cmpsb             ;compare item to name for name length
  476.               jne      env_var_find_next ;if not found, scan on
  477.  
  478.               cmp      byte ptr es:[di],'='   ;check next byte for '='
  479.               jne      env_var_find_next ;if found, go calc length
  480.  
  481.               mov      ah,0              ;say compare ok
  482. env_var_find_next:                      
  483.               pop      di                ;restore string pointers
  484.               pop      si                
  485.  
  486.               xor      al,al             ;look for end of current substring
  487.               mov      cx,dx             ;search remainder of string
  488.               mov      dx,di             ;save search start
  489.               repnz    scasb             ;search for a zero
  490.               jne      env_var_find_end  ;none found, error
  491.  
  492.               cmp      ah,0              ;did original compare fly?
  493.               je       env_var_find_found;if so, then pass length, etc
  494.                             
  495.               cmp      byte ptr es:[di],0  ;check next byte for zero
  496.               je       env_var_find_end  ;if found, name not found
  497.                                           
  498.               mov      dx,cx             ;save length of string remaining
  499.               jmp      env_var_find_loop ;and loop on
  500.  
  501. env_var_find_end:
  502.               xor      cx,cx             ;length = 0, none found
  503.               stc                        ;set error flag
  504.               jmp      env_var_find_exit
  505.  
  506. env_var_find_found:
  507.               mov      cx,di             ;save count of end of string
  508.               mov      di,dx             ;restore search start
  509.               sub      cx,di             ;calc length of search
  510.               dec      cx                ;less length of zero
  511.               clc                        ;no errors
  512.  
  513. env_var_find_exit:
  514.               pop      dx
  515.               pop      bx                ;restore registers
  516.               pop      ax
  517.               ret
  518. env_var_find  endp
  519.  
  520.  
  521. null_var      dw       -1
  522.  
  523. env_var_add   proc near                     ;add  environment variable
  524.                                             ;expression ->ds:si, length in cx
  525.               push    ax                    ;save registers
  526.               push    bx
  527.               push    dx
  528.  
  529.               mov     dx,offset addmsg
  530.               call    type_string
  531.               mov     bx,cx
  532.               push    si
  533.               mov     si,offset null_var  ;send on wild goose chase
  534.               mov     cx,2                ;looking for  x'ffff'
  535.               call    env_var_find        ;es:di points to end of env
  536.               pop     si
  537.               jnc     env_var_add_env_bad 
  538.                                           ;es:di now points to end of env
  539.               call    get_sb_size         ;get length of env area in cx
  540.               add     cx,sb_head_length   ;add head length for offsets
  541.               sub     cx,bx               ;deduct length of string
  542.               sub     cx,2                ;deduct length of flag
  543.               cmp     di,cx               ;compare to where we add
  544.               ja      env_var_add_bad     ;if no space, too bad
  545.  
  546.               mov     cx,bx               ;length of string to add
  547.               rep     movsb               ;do the deed
  548.               xor     ax,ax               ;make flag of two zeros
  549.               stosw                       ;add is on
  550.  
  551.               jmp     env_var_add_good 
  552.  
  553. env_var_add_env_bad:
  554.               mov     dx,offset addbadmsg
  555.               call    type_string
  556.  
  557. env_var_add_bad:
  558.               stc
  559.               jmp     env_var_add_exit
  560.  
  561. env_var_add_good:
  562.               clc
  563. env_var_add_exit:
  564.               pop     dx                  ;restore registers
  565.               pop     bx
  566.               pop     ax
  567.               ret
  568.  
  569. env_var_add   endp
  570.  
  571.  
  572. env_var_remove proc near                ;remove environment variable
  573.                                         ;at es:di, length in cx 
  574.               push    cx
  575.               push    dx
  576.               push    ds
  577.               push    di
  578.               push    si
  579.  
  580.               cld                      ;move left to right
  581.  
  582.               mov     dx,offset removemsg
  583.               call    type_string
  584.  
  585.               inc     cx                  ;add 1 for zero byte
  586.               mov     dx,cx               ;save length of var
  587.               call    get_sb_size         ;cx gets length of env area
  588.               add     cx,sb_head_length   ;add header length for offsets
  589.               sub     cx,di               ;deduct where we start
  590.               sub     cx,dx               ;deduct length of removed variable
  591.  
  592.               mov     si,di               ;move from next variable
  593.               add     si,dx               ;add my length
  594.                 
  595.               push    es                  ;do all the work in es:
  596.               pop     ds
  597.  
  598.               rep     movsb               ;do the move
  599.                 
  600.               pop     si
  601.               pop     di
  602.               pop     ds
  603.               pop     dx
  604.               pop     cx
  605.               ret
  606. env_var_remove  endp
  607.  
  608.  
  609. env_set       proc    near                ;change environment per ds:si
  610.               push    ax                  
  611.               push    bx                  ;ds:si points to:
  612.               push    cx                  ; length  db  ?
  613.               push    di
  614.               push    ds                  ; data    db  'name=value'
  615.               push    es
  616.               push    si
  617.  
  618.               xor     ax,ax               ;set length of local set string
  619.               lodsb                       ;get length, push di forward
  620.               mov     cx,ax               ;length of set string in cx
  621.               call    sb_anal             ;analyze the storage block chain
  622.                                           ;to find command processor(s)
  623.               cmp     sb_secondary_env,0  ;is there a secondary command proc?
  624.               je      env_set_shell       ;if not, use primary
  625.  
  626.               mov     es,sb_secondary_env ;command processor is secondary
  627.               jmp     env_set_command
  628.  
  629. env_set_shell:                            ;command processor is shell
  630.               mov     es,sb_shell_env
  631. env_set_command:  
  632.               call    env_var_name        ;find what we want set at call
  633.                                           ;ds:si -> expression, cx has length
  634.                                           ;at return ds:si -> name
  635.                                           ;cx is length of name
  636.               jc      env_set_syntax_err  ;if not found, error             
  637.  
  638.               mov     bx,cx               ;calculate new length of set string
  639.               inc     bx                  ;add 1 for '='
  640.               add     bx,dx               ;add length of set string
  641.  
  642.               call    env_var_find        ;find variable in environment block
  643.                                           ;at return, es:di -> start of env str
  644.                                           ;cx is length of env str
  645.               jc      env_set_add         ;if not found, just add
  646.  
  647.               call    env_var_remove      ;remove variable at es:di from env
  648.               cmp     dx,0                ;check out length of data to add
  649.               je      env_set_exit        ;if zero, just exit
  650.  
  651. env_set_add:                              
  652.               mov     cx,bx               ;restore length of variable
  653.               call    env_var_add         ;add new variable to set string
  654.               jc      env_set_no_space
  655.               jmp     env_set_exit
  656.  
  657. env_set_no_space:
  658.               mov     dx,offset env_set_nospace
  659.               jmp     env_set_type
  660.  
  661. env_set_syntax_err:
  662.               mov     dx,offset env_set_syntax
  663. env_set_type:
  664.               call    type_string
  665. env_set_error:
  666.               stc
  667. env_set_exit:
  668.               pop     si
  669.               pop     es
  670.               pop     ds
  671.               pop     di
  672.               pop     cx
  673.               pop     bx
  674.               pop     ax
  675.               ret
  676. env_set       endp
  677.  
  678. code_seg      ends   
  679.               end     
  680.  
  681.